home *** CD-ROM | disk | FTP | other *** search
- /* error.c -- some rudimentary error support */
-
- /*
- * srouted -- silent routing daemon
- * Copyright (C) 1995 Kevin Buhr
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #ifndef lint
- static char rcsid[] = "$Id: error.c,v 1.5 1995/02/17 17:43:27 buhr Exp $";
- #endif /* not lint */
-
- #include "defs.h"
- #include "table.h"
- #include "error.h"
-
- #include <stdio.h>
- #include <stdarg.h>
- #include <errno.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
-
-
- enum er_form {
- ERCF_, /* void */
- ERCF_E, /* int errno */
- ERCF_IE, /* int ioctl, int errno */
- ERCF_RF, /* struct rip *rip, int length, struct tb_address *from */
- ERCF_RFE, /* struct rip *rip, int length, struct tb_address *from, int entry */
- ERCF_RFEM, /* struct rip *rip, int length, struct tb_address *from, int entry, int metric */
- ERCF_RFEMR, /* struct rip *rip, int length, struct tb_address *from, int entry, int metric, int route */
- ERCF_I, /* struct iface *iface */
- ERCF_IR, /* struct iface *iface, struct tb_route *route */
- ERCF_ID, /* struct iface *iface, struct tb_address *dest */
- ERCF_SS, /* int size, int size */
- ERCF_A, /* struct tb_address *address */
- ERCF_P, /* int port */
- ERCF_T, /* no args---dump routing table */
- ERCF_TTT, /* int now, int next, int pause */
- ERCF_R, /* int route */
- ERCF_LAST
- };
-
- #define ERCN_MASK 0xF000
- #define ERCN_SHIFT 12
- #define ERCN_0 0x0000
- #define ERCN_1 0x1000
- #define ERCN_2 0x2000
- #define ERCN_3 0x3000
- #define ERCN_4 0x4000
-
- static struct er_table {
- enum er_code ert_code;
- short ert_form;
- char *ert_text;
- } er_table[] = {
- ERC_NOERROR, ERCF_, NULL,
-
- /* input.c */
- ERCIN_BADFROM, ERCF_, "Received RIP from invalid address",
- ERCIN_VERS0, ERCF_RF, "Received RIP packet with version zero",
- ERCIN_CZ, ERCF_RF, "Received RIP packet with bad header reserved areas",
- ERCIN_CZE, ERCF_RFE, "Received RIP packet with bad entry reserved areas",
- ERCIN_CMD0, ERCF_RF, "Received RIP packet with command code zero",
- ERCIN_UNKCMD, ERCF_RF, "Received RIP packet with unknown command code",
- ERCIN_CMD34, ERCF_RF, "Received RIP packet using obsolete trace commands",
- ERCIN_CMD5, ERCF_RF, "Received RIP packet using Sun's reserved command code 5",
- ERCIN_UNKAF, ERCF_RFE, "Received RIP packet entry for unknown address family",
- ERCIN_RESPPORT, ERCF_RF, "Received RIP response from invalid port",
- ERCIN_RESPREMOTE, ERCF_RF, "Received RIP response from remote source",
- ERCIN_BADMETRIC, ERCF_RFE, "Received RIP response entry with invalid metric",
- ERCIN_BADADDR, ERCF_RFE, "Received RIP response entry with bad address",
- ERCIN_RTFULL, ERCF_, "Route table full",
- ERCIN_RTSUPER, ERCF_A, "Received unsubnetted route for subnetted network",
-
- /* output.c */
- ERCOUT_SENDTO, ERCF_E, "\"sendto\" call failed",
- ERCOUT_FULLOUT, ERCF_, "Filled output buffer",
- ERCOUT_BADIFACE, ERCF_I, "Couldn't broadcast to interface",
-
- /* kernel.c */
- ERCKR_NOIPSOCK, ERCF_E, "Failed to open internet datagram socket",
- ERCKR_IOCTL, ERCF_IE, "Interface configuration IOCTL failed",
- ERCKR_IFFULL, ERCF_, "Insufficient interface configuration entries to store interface configuration",
- ERCKR_XADDRT, ERCF_E, "Failed to add route",
- ERCKR_XDELRT, ERCF_E, "Failed to delete route",
-
- /* table.c */
- ERCTB_RTFULL, ERCF_, "Route table full",
- ERCTB_RTDUP, ERCF_IR, "Two interfaces had same destination",
- ERCTB_INVDEST, ERCF_ID, "Interface destination not a valid IP address",
- ERCTB_BADSUPER, ERCF_A, "Subnetted net appeared as destination in route table",
-
- /* driver.c */
- ERCDR_SYNTAX, ERCF_, "Syntax: srouted [-t ...]",
- ERCDR_NOTROOT, ERCF_, "Must be root",
- ERCDR_BIGRIP, ERCF_SS, "Received oversized packet",
- ERCDR_SELECT, ERCF_E, "\"select\" call failed",
- ERCDR_ADDRSIZE, ERCF_SS, "Packet source address had bad size",
- ERCDR_SOCKET, ERCF_E, "\"socket\" call failed",
- ERCDR_FCNTL, ERCF_E, "\"fcntl(O_NONBLOCK)\" failed",
- ERCDR_SSOPT, ERCF_E, "\"setsockopt(SO_BROADCAST)\" failed",
- ERCDR_BIND, ERCF_E, "\"bind\" call failed",
- ERCDR_RECVFROM, ERCF_E, "\"recvfrom\" call failed",
- ERCDR_GETSERV, ERCF_, "Failed to get \"route\" service by name",
-
- /* notification/tracing codes start here */
- /* driver.c */
- ERCDR_USINGPORT, ERCF_P | ERCN_2, "[driver] Using \"route\" port",
- ERCDR_GETIFCONF, ERCF_ | ERCN_1, "[driver] Getting current interface configuration",
- ERCDR_INITROUTE, ERCF_ | ERCN_1, "[driver] Constructing initial route table entries",
- ERCDR_GETTABLE, ERCF_ | ERCN_1, "[driver] Broadcasting for copy of whole table",
- ERCDR_DUMPROUTE, ERCF_T | ERCN_0, "[driver] dumproute==1, dumping routing table",
- ERCDR_SCHED, ERCF_TTT | ERCN_4, "[driver] \"select\" loop scheduling status",
- ERCDR_TIMEOUT, ERCF_ | ERCN_4, "[driver] \"select\" loop timed out",
- ERCDR_GOTINPUT, ERCF_ | ERCN_4, "[driver] \"select\" loop got input",
-
- /* input.c */
- ERCIN_GOTINPUT, ERCF_ | ERCN_4, "[input] Processing received packet",
- ERCIN_IGNOREREQUEST, ERCF_RF|ERCN_4, "[input] Ignoring request received on \"route\" port",
- ERCIN_GOTREQUEST, ERCF_RF|ERCN_1, "[input] Received a request packet",
- ERCIN_REQWHOLE, ERCF_ | ERCN_2, "[input] Responding to request for whole routing table",
- ERCIN_REQENTRY, ERCF_RFEM|ERCN_3, "[input] Processing request entry",
- ERCIN_REQANSWER, ERCF_ | ERCN_2, "[input] Responding to normal request",
- ERCIN_GOTRESPONSE, ERCF_RF|ERCN_2, "[input] Received a response packet",
- ERCIN_RESENTRY, ERCF_RFEMR|ERCN_3, "[input] Processing response entry",
- ERCIN_IGNOREHOST, ERCF_R| ERCN_4, "[input] Ignoring host route, had net route",
- ERCIN_RESADDED, ERCF_R | ERCN_4, "[input] Added route from response packet",
- ERCIN_HADROUTE, ERCF_ | ERCN_4, "[input] Comparing new with existing route",
- ERCIN_REPEATROUTE, ERCF_| ERCN_4, "[input] New and existing are identical, updating timer",
- ERCIN_RESDELETED, ERCF_R| ERCN_4, "[input] Deleting route based on response entry",
- ERCIN_RESIGNORED, ERCF_ | ERCN_4, "[input] Response entry route ignored",
-
- /* output.c */
- ERCOUT_SENDING, ERCF_RF | ERCN_2, "[output] Sending a RIP",
- ERCOUT_UPDATE, ERCF_ | ERCN_4, "[output] Update triggered and ignored",
- ERCOUT_SENDTABLE, ERCF_A| ERCN_1, "[output] Sending a copy of whole routing table",
- ERCOUT_GETTABLE, ERCF_ID| ERCN_1, "[output] Broadcasting request for whole table",
-
- /* kernel.c */
- ERCKR_DELRT, ERCF_R | ERCN_4, "[kernel] Deleted kernel route",
- ERCKR_ADDRT, ERCF_R | ERCN_4, "[kernel] Added kernel route",
-
- /* table.c */
- ERCTB_ADDEDSUPER, ERCF_R| ERCN_2, "[table] Added dummy supernet route",
- ERCTB_IFDEFAULT, ERCF_ID| ERCN_2, "[table] Constructed default route for interface",
- ERCTB_ADDRT, ERCF_R | ERCN_1, "[table] Added route",
- ERCTB_DELRT, ERCF_R | ERCN_1, "[table] Deleted route",
- ERCTB_KEPTRT, ERCF_R | ERCN_1, "[table] Keeping dead route",
- ERCTB_KILLRT, ERCF_R | ERCN_1, "[table] Killing dead route",
-
- /* timer.c */
- ERCTM_SETTO, ERCF_R | ERCN_4, "[timer] Setting timeout timer",
- ERCTM_SETGC, ERCF_R | ERCN_4, "[timer] Setting garbage collection timer",
- ERCTM_KILL, ERCF_R | ERCN_4, "[timer] Killing timers",
- ERCTM_TIMEOUT, ERCF_R | ERCN_2, "[timer] Timeout timer expired",
- ERCTM_GARBCOLL, ERCF_R | ERCN_2, "[timer] Garbage collection timer expired",
- ERCTM_NETO, ERCF_R | ERCN_4, "[timer] Next event is \"timeout\"",
- ERCTM_NEGC, ERCF_R | ERCN_4, "[timer] Next event is \"garbage collection\"",
- ERCTM_NENONE,ERCF_ | ERCN_1, "[timer] No events pending",
-
- ERC_LAST, ERCF_, "Unknown error code received!!!"
- };
-
- static char *er_severity[] = { "note", "fatal error", "warn", "weakwarn", "note" };
-
-
- /*
- * Produce dot-form of a sockaddr
- */
-
- static char *er_satoa( struct sockaddr *sa )
- {
- return( inet_ntoa( ((struct sockaddr_in *) sa)->sin_addr ) );
- }
-
-
- /*
- * Dump RIP parts
- */
-
- void er_dumprip( struct rip *rip, int length, struct tb_address *from )
- {
- fprintf(stderr, " RIP packet of length %d address %s port %d:\n RIP cmd %s(%d) vers %d\n",
- length, er_satoa( &from->tba_addr ), from->tba_port,
- rip->rip_cmd == RIPCMD_REQUEST ? "REQUEST"
- : rip->rip_cmd == RIPCMD_RESPONSE ? "RESPONSE"
- : "",
- rip->rip_cmd, rip->rip_vers);
- }
- void er_dumpripe( struct rip *rip, int entry )
- {
- fprintf(stderr, " entry %d dest %s (af=%d) metric %lu\n",
- entry,
- er_satoa( &rip->rip_nets[entry].rip_dst ),
- ntohs(rip->rip_nets[entry].rip_dst.sa_family),
- ntohl(rip->rip_nets[entry].rip_metric) );
- }
-
-
- /*
- * Log an error
- */
-
- void er_log( int level, enum er_code code, ... )
- {
- struct tb_address *address;
- struct tb_route *route;
- struct tb_iface *iface;
- struct rip *rip;
- struct er_table *error;
- int errno, ioctl, length, length2, rti;
- time_t now, next, pause;
- short form;
-
- va_list arg;
- va_start( arg, code );
-
- if( level > g_tracelevel )
- return;
-
- for( error=&er_table[0]; error->ert_code!=ERC_LAST; error++ ) {
- if( error->ert_code == code )
- break;
- }
-
- if( error->ert_code == ERC_LAST )
- level = ERL_DIE;
-
- if( level == ERL_NOTE
- && ((error->ert_form & ERCN_MASK) >> ERCN_SHIFT) > g_tracenlevel )
- return;
-
- form = error->ert_form & ~ERCN_MASK;
-
- fprintf( stderr, "srouted %s: %s",
- er_severity[level+1],
- error->ert_text );
-
- switch( form ) {
-
- case ERCF_:
- fprintf(stderr, "\n");
- break;
-
- case ERCF_E:
- fprintf(stderr, ": %s\n", strerror( va_arg(arg, int) ) );
- break;
-
- case ERCF_IE:
- ioctl=va_arg(arg,int);
- errno=va_arg(arg,int);
-
- fprintf(stderr, ": ioctl %d: %s\n", ioctl, strerror( errno ) );
- break;
-
- case ERCF_RF:
- case ERCF_RFE:
- case ERCF_RFEM:
- case ERCF_RFEMR:
- rip = va_arg( arg, struct rip * );
- length = va_arg( arg, int );
- address = va_arg( arg, struct tb_address * );
- fprintf( stderr, ":\n");
- er_dumprip( rip, length, address );
- if( form != ERCF_RF ) {
- er_dumpripe( rip, va_arg( arg, int ) );
- if( form != ERCF_RFE ) {
- fprintf( stderr, " new cost %d\n", va_arg( arg, int ) );
- if( form != ERCF_RFEM ) {
- rti = va_arg( arg, int );
- if( rti == -1 ) {
- fprintf( stderr, " no existing route known\n" );
- } else {
- er_dumproute( rti );
- }
- }
- }
- }
- break;
-
- case ERCF_ID:
- iface = va_arg( arg, struct tb_iface * );
- address = va_arg( arg, struct tb_address * );
- fprintf( stderr, ": iface %s, dest %s\n",
- iface->tbif_dev,
- er_satoa( &address->tba_addr ) );
- break;
-
- case ERCF_I:
- iface = va_arg( arg, struct tb_iface * );
- fprintf( stderr, ": iface %s\n",
- iface->tbif_dev );
- break;
-
- case ERCF_IR:
- iface = va_arg( arg, struct tb_iface * );
- route = va_arg( arg, struct tb_route * );
- fprintf( stderr, ": iface-1 %s, iface-2 %s, route %s\n",
- iface->tbif_dev,
- route->tbrt_iface == -1 ? "Oops!" :
- tb_iface[route->tbrt_iface].tbif_dev,
- er_satoa( &address->tba_addr ) );
- break;
-
- case ERCF_SS:
- length = va_arg( arg, int );
- length2 = va_arg( arg, int );
- fprintf( stderr, ": got %d, expected %d\n", length, length2 );
- break;
-
- case ERCF_A:
- address = va_arg( arg, struct tb_address * );
- fprintf( stderr, ": address %s\n",
- er_satoa( &address->tba_addr ) );
- break;
-
- case ERCF_P:
- fprintf(stderr, ": port %hu\n", va_arg( arg, unsigned short) );
- break;
-
- case ERCF_T:
- fprintf(stderr,":\n");
- er_dumproute( -1 ); /* dump the routing table */
- break;
-
- case ERCF_R:
- fprintf(stderr,":\n");
- er_dumproute( va_arg( arg, int ) ); /* dump one route entry */
- break;
-
- case ERCF_TTT:
- now = va_arg( arg, time_t );
- next = va_arg( arg, time_t );
- pause = va_arg( arg, time_t );
- fprintf(stderr, ": now=%ds, next=%ds, pause=%ds\n",
- (int) now, (int) next, (int) pause);
- break;
-
- default:
- break; /* this is an error of course, but let's ignore it */
- }
-
- if( level == ERL_DIE ) {
- exit(1);
- }
-
- }
-
-
- /*
- * Dump ONE route table row
- */
-
- static void er_dumparoute( int i )
- {
- fprintf(stderr, " %15.15s ", er_satoa( &tb_route[i].tbrt_dst ) );
- fprintf(stderr, "%15.15s ", er_satoa( &tb_route[i].tbrt_gateway ) );
- fprintf(stderr, "%15.15s ", er_satoa( &tb_route[i].tbrt_mask ) );
- fprintf(stderr, "%04X %5d %8.8s\n",
- tb_route[i].tbrt_flags,
- tb_route[i].tbrt_metric,
- tb_route[i].tbrt_iface != -1 ?
- tb_iface[tb_route[i].tbrt_iface].tbif_dev :
- "none" );
- }
-
-
- /*
- * Dump the internal routing table
- */
-
- void er_dumproute( int rti )
- {
- int i;
-
- fprintf(stderr, " Destination Gateway Mask Flags Metric Iface\n");
-
- if( rti == -1 ) {
- for( i=0; i<TB_ROUTE_SIZE; i++ ) {
- if( (tb_route[i].tbrt_flags & TBRTF_USED)==0 )
- continue;
- er_dumparoute( i );
- }
- } else {
- er_dumparoute( rti );
- }
- }
-
-
- /*
- * Notify user of trace level change
- */
-
- void er_tracechange( void )
- {
- fprintf(stderr,"srouted note: [error] TRACE LEVEL CHANGE: tracelevel=%d, tracenlevel=%d\n", g_tracelevel, g_tracenlevel);
- }
-